const Parse = require('parse/node');
const _=require('lodash');
const CabinetObj = Parse.Object.extend("AutoBorrow_Cabinets");
const ParseHelper = require('../helpers/parse');
const GridObj = Parse.Object.extend("AutoBorrow_CabinetGrids");
const CabinetLogObj = Parse.Object.extend("AutoBorrow_CabinetLogs");
const TakenRecordObj = Parse.Object.extend("AutoBorrow_TakenRecords");
const KindService=require("./kind");
const ExcelService = require("./excel");
// // 指定 WebSocket 服务器的地址
// const cabinetServerUrl =config.cabinetServerUrl;

// // 创建一个到 WebSocket 服务器的连接
// const ws = new WebSocket(`ws://${cabinetServerUrl}`);

const ws=require("../websocket");

//创建名单
async function add(cabinet){
    const borrowTimeObj=new CabinetObj(cabinet);
    await borrowTimeObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(borrowTimeObj);
}

//删除
async function remove(cabinetId){
    const cabinetObj=CabinetObj.createWithoutData(cabinetId);
    cabinetObj.set("isDeleted",true);
    await cabinetObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(cabinetObj);
}


async function update(key,value,id){
    const cabinetObj= CabinetObj.createWithoutData(id);
    cabinetObj.set(key,value);
    await cabinetObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(cabinetObj);
}

async function addGrids(cabinet){
    const {count,HID}=cabinet;
    const grids=[];
    for(let i=1;i<=count;i++){
            grids.push({
                number:i,
                cabinetId:HID
            })
    }
    const gridObjs=grids.map(grid=>{
        const gridObj=new GridObj();
        return gridObj.save(grid,{ useMasterKey: true });
    });
    return gridObjs;
}
async function getEmptyGrid(cabinetId){
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",cabinetId);
    // query.doesNotExist("kindId");
    // query.ascending("sNumber");
    const grids=await query.find({ useMasterKey: true });    
    const _grids=ParseHelper.toJSONList(grids);
    //将格子中sNumber转数字并按照升序排序,用lodash的sortBy方法
    const  sortedGrids=_.sortBy(_grids,grid=>Number(grid.sNumber));
    //获取所有没有kindId的格子
    const emptyGrdis=sortedGrids.find(grid=>!grid.kindId);
    return emptyGrdis;
}

async function saveDevice(cabinetId,grid,device){
    console.log(cabinetId,grid,device);
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",cabinetId.toString());
    query.equalTo("number",Number(grid));
    const gridObj=await query.first({ useMasterKey: true });
    gridObj.set("isOccupied",true);
    gridObj.set("barcode",device.barcode);
    gridObj.set("kindId",device.kindId);
    await gridObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(gridObj);
}

async function getDeviceGrid(cabinetId,kindId){
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",cabinetId);
    query.equalTo("kindId",kindId);
    const grid=await query.first({ useMasterKey: true });
    return ParseHelper.toJSON(grid);
}

async function getSuppliesGrid(kindId){
    const query=new Parse.Query(GridObj);
    query.equalTo("kindId",kindId);
    const grid=await query.find({ useMasterKey: true });
    return ParseHelper.toJSONList(grid);
}

async function clearDeviceGrid(gridId){
    const gridObj=GridObj.createWithoutData(gridId);
    gridObj.set("isOccupied",false);
    gridObj.set("barcode",null);
    gridObj.set("kindId",null);
    await gridObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(gridObj);
}

async function clearSuppliesGrid(gridId, count) {
    const gridObj = GridObj.createWithoutData(gridId);

    // 获取当前网格的 count 值
    await gridObj.fetch({ useMasterKey: true });
    const currentCount = gridObj.get("count");

    if (currentCount === count) {
        // 如果 count 相等，则清除网格信息
        gridObj.set("isOccupied", false);
        gridObj.set("barcode", null);
        gridObj.set("kindId", null);
        gridObj.set("count", 0);
    } else if (currentCount > count) {
        // 如果当前 count 大于输入的 count，则减少库存
        gridObj.set("count", currentCount - count);
    } else {
        throw new Error("库存不足，无法清除指定数量");
    }

    // 保存更改
    await gridObj.save(null, { useMasterKey: true });
    return ParseHelper.toJSON(gridObj);
}



async function clearDeviceGrid(gridId){
    const gridObj=GridObj.createWithoutData(gridId);
    gridObj.set("isOccupied",false);
    gridObj.set("barcode",null);
    gridObj.set("kindId",null);
    await gridObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(gridObj);
}

async function getGrid(kindId,cabinetId){
    //获取柜子中有物品的格子
    const query=new Parse.Query(GridObj);
    query.equalTo("kindId",kindId);
    // query.equalTo("isOccupied",true);
    query.equalTo("cabinetId",cabinetId);
    console.log(cabinetId)
    let grid=await query.first({ useMasterKey: true }).then(ParseHelper.toJSON);
    //如果没有物品的格子，获取一个空格子
    if(!grid){
        grid=await getEmptyGrid(cabinetId);
    }
    const count=grid?grid.count:0;
    const kind=await KindService.getKindById(kindId);
    const occupyCount=kind&&kind.occupyCount?kind.occupyCount:0;
    //如果格子中的物品数量大于等于占用数量，获取一个空格子
    if(occupyCount&&occupyCount<=count){
        grid=await getEmptyGrid(cabinetId);
    }
    return grid;
}

async function getKindGrid(kindId,cabinetId){
    //获取柜子中有物品的格子
    const query=new Parse.Query(GridObj);
    query.equalTo("kindId",kindId);
    query.notEqualTo("count",0);
    query.equalTo("cabinetId",cabinetId);
    let grid=await query.first({ useMasterKey: true }).then(ParseHelper.toJSON);
    return grid; 
}

async function storeItem(cabinetId,grid,boardid,count,kindId){
    const cabinet=await getCabinetByHID(cabinetId);
    if(!cabinet){
        throw new Error("未找到对应的物料柜");
    }
    const _cabinetId=cabinet.objectId;
    //先找到已经存过该物品的格子
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",_cabinetId);
    query.equalTo("kindId",kindId);
    query.equalTo("number",Number(grid));
    query.equalTo("cid",(boardid).toString());
    let parseGrid=await query.first({ useMasterKey: true });
    console.log ("storeItem",parseGrid);
    if(parseGrid){
        parseGrid.increment("count",Number(count));
        await parseGrid.save(null,{ useMasterKey: true });
        return ParseHelper.toJSON(parseGrid);   
    }
    else{
        const query=new Parse.Query(GridObj);
        query.equalTo("cabinetId",_cabinetId);
        query.equalTo("number",Number(grid));
        query.equalTo("cid",boardid);
        let parseGrid=await query.first({ useMasterKey: true });
        if(parseGrid){
            parseGrid.set("kindId",kindId);
            parseGrid.set("count",Number(count));
            parseGrid.set("status",'occupied');
            await parseGrid.save(null,{ useMasterKey: true });
            return ParseHelper.toJSON(parseGrid);   
        }
    }
}


async function storeFaultItem(cabinetId,grid,boardid,count,kindId){
     const cabinet=await getCabinetByHID(cabinetId);
    if(!cabinet){
        throw new Error("未找到对应的物料柜");
    }
    const _cabinetId=cabinet.objectId;
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",_cabinetId);
    query.equalTo("number",Number(grid));
    query.equalTo("cid",boardid);
    let parseGrid=await query.first({ useMasterKey: true });
    if(parseGrid){
        parseGrid.set("kindId",kindId);
        parseGrid.set("count",Number(count));
        parseGrid.set("status",'occupied');
        //标记格子放的是故障物品
        parseGrid.set("isFaultItem",true);
        await parseGrid.save(null,{ useMasterKey: true });
        return ParseHelper.toJSON(parseGrid);   
    }
}

async function takeItem(device,grid,cid,count,kindId,username){
    await saveTakenRecord(device,grid,cid,count,kindId,username);
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",device);
    query.equalTo("kindId",kindId);
    query.equalTo("number",Number(grid));
    query.equalTo("cid",cid.toString());
    let gridObj=await query.first({ useMasterKey: true });
    console.log("takeItem",ParseHelper.toJSON(gridObj));
    //获取柜子中物品的数量
    if(gridObj){
        const gridCount=gridObj.get("count");
        //如果柜子中物品的数量等于要取的数量，清空格子
        if(gridCount===count){
            gridObj.set("kindId",null);
            gridObj.set("count",0);
        }else{
            gridObj.increment("count",-count);
        }
        await gridObj.save(null,{ useMasterKey: true });
    }
    // const cid=gridObj.get("cid");
    await openGrid(device,grid,cid);
    return ParseHelper.toJSON(gridObj);
}

async function openGrid(device,grid,cid){
    
    const data={"type":"open","lockerid":device,"boardid":Number(cid),"portid":Number(grid),"cmd":"server"}
    ws.send(JSON.stringify(data));
}

async function openCabinetGrid(grid){
     const query=new Parse.Query(CabinetObj);
    query.equalTo("objectId",grid.cabinetId);
    const cabinet=await query.first({ useMasterKey: true });
    if(!cabinet){
        throw new Error("未找到对应的物料柜");
    }
    const _cabinetId=cabinet.get("HID");
    await openGrid(_cabinetId,grid.boardNumber,grid.cid);
    return grid;
}

async function  getCabinetById(id) {
   const query=new Parse.Query(CabinetObj);
   query.equalTo("objectId",id);
   return await query.first({ useMasterKey: true }).then(ParseHelper.toJSON);

}

async function saveTakenRecord(device,grid,boardid,count,kindId,username,isReturn){
    const record=new TakenRecordObj();
    record.set("device",device);
    record.set("grid",grid.toString());
    record.set("boardid",boardid.toString());
    record.set("count",Number(count));
    record.set("kindId",kindId);
    record.set("username",username);
    record.set("isReturn",isReturn);
    await record.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(record);
}

async function getDeviceLocation(cabinetId,kindId,count){
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",cabinetId);
    query.equalTo("kindId",kindId);
    if(count&&count>0){
        query.lessThan("count",count);
    }
    const grid=await query.first({ useMasterKey: true });
    return ParseHelper.toJSON(grid);
}
async function return_good(cabinetId,grid,cid,kindId){
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",cabinetId);
    query.equalTo("number",grid);
    query.equalTo("cid",Number(cid));
    query.equalTo("kindId",kindId);
    let gridObj=await query.first({ useMasterKey: true });
    gridObj.increment("count",1);
    await gridObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(gridObj);
}

async function addGrid(grid){
    const gridObj=new GridObj();
    gridObj.set("sNumber",grid.sNumber);
    gridObj.set("cabinetId",grid.cabinetId);
    gridObj.set("number",Number(grid.number));
    gridObj.set("cid",grid.cid);
    await gridObj.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(gridObj);
}
async function checkExcelFile(filePath,nameRowNumber,firstDataRowNumber,fieldsMapping){
    const gridsData=await ExcelService.parseExcelFileFirstSheet(filePath,nameRowNumber,firstDataRowNumber);
    //取得前5行作为样例数据
    const exampleRows=_.take(gridsData,5);
    const mappedExampleRows=exampleRows.map(row=>mappingUserData(row,fieldsMapping));
    const result={
        exampleRows,
        mappedExampleRows,
        filePath,
        count:gridsData.length
    };
    if(!mappedExampleRows[0].hasOwnProperty("cid")){
        result.error= "缺少控制板编号"
    }
    return result;
}

//根据fieldsMapping修改userData中的key
function mappingUserData(userData, fieldsMapping){
    const mappedUserData={...userData};//复制要处理的数据
    Object.keys(mappedUserData).forEach(function(key) {
        const dbFieldName=fieldsMapping[key];
        if(dbFieldName){
            mappedUserData[dbFieldName] = mappedUserData[key];
            delete mappedUserData[key];
        }
    });
    return mappedUserData;
}
async function importExcelFile(filePath,nameRowNumber,firstDataRowNumber,fieldsMapping,cabinetId){
    var gridsData=await ExcelService.parseExcelFileFirstSheet(filePath,nameRowNumber,firstDataRowNumber);
    const mappedExampleRows=gridsData.map(row=>mappingUserData(row,fieldsMapping));
    const objs=mappedExampleRows.map(grid=>{
        const parseGrid =  new GridObj();
        parseGrid.set("sNumber",grid.sNumber)
        parseGrid.set("cid",grid.cid)
        parseGrid.set("number",Number(grid.number))
        parseGrid.set("cabinetId",cabinetId)
        return parseGrid;
    });
    const grids= await Parse.Object.saveAll(objs,{ useMasterKey: true });
    return {successCount:grids.length};
}

async function changeHID(HID,id){
    const cabinetObj=CabinetObj.createWithoutData(id);
    cabinetObj.set("HID",HID);
    await cabinetObj.save(null,{ useMasterKey: true });
    await changeGridCabinetId(HID);
    return ParseHelper.toJSON(cabinetObj);
}

async function changeGridCabinetId(HID){
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",HID);
    const grids=await query.find({ useMasterKey: true });
    grids.forEach(grid=>{
        grid.set("cabinetId",HID);
    });
    await Parse.Object.saveAll(grids,{ useMasterKey: true });
    return grids;
}

async function getCabinetGrids(cabinetId){
    const cabinetQuery=new Parse.Query(CabinetObj);
    cabinetQuery.equalTo("HID",cabinetId);
    const cabinet=await cabinetQuery.first({ useMasterKey: true });
    if(!cabinet){
        throw new Error("未找到对应的物料柜");
    }
    const query=new Parse.Query(GridObj);
    query.equalTo("cabinetId",cabinet.id);
    const grids=await query.find({ useMasterKey: true });
    const gridList=ParseHelper.toJSONList(grids);   
    const kindIds=_.uniq(gridList.map(grid=>grid.kindId).filter(id=>id));
    const kinds=await KindService.getKindsByIds(kindIds);
    const kindMap=_.keyBy(kinds,"objectId");
    gridList.forEach(grid=>{
        if(grid.kindId){
            grid.kind=kindMap[grid.kindId].name;
        }
    });
    //将格子中的sNumber转数字并按照升序排序,用lodash的sortBy方法
    const sortedGrids=_.sortBy(gridList,grid=>Number(grid.number));
   return {
        cabinet: ParseHelper.toJSON(cabinet),
        grids: sortedGrids
    };
}

async function getCabinetByHID(HID){
    const query=new Parse.Query(CabinetObj);
    query.equalTo("HID",HID);
    const cabinet=await query.first({ useMasterKey: true });
    if(!cabinet){
        throw new Error("未找到对应的物料柜");
    }
    return ParseHelper.toJSON(cabinet);
}

async function saveCabinetLog(cabinetId,grid,username,action="open"){
    const log=new CabinetLogObj();
    log.set("cabinetId",cabinetId);
    log.set("grid",grid);
    log.set("username",username);
    log.set("action",action);
    await log.save(null,{ useMasterKey: true });
    return ParseHelper.toJSON(log);
}

async function getCabinets(){
    const query=new Parse.Query(CabinetObj);
    query.notEqualTo("isDeleted",true);
    const cabinets=await query.find({ useMasterKey: true });
    return ParseHelper.toJSONList(cabinets);
}


module.exports={
    add,
    remove,
    update,
    addGrids,
    getEmptyGrid,
    saveDevice,
    getDeviceGrid,
    clearDeviceGrid,
    getGrid,
    storeItem,
    takeItem,
    getDeviceLocation,
    return_good,
    saveTakenRecord,
    addGrid,
    importExcelFile,
    checkExcelFile,
    changeHID,
    getKindGrid,
    getSuppliesGrid,
    clearSuppliesGrid,
    getCabinetGrids,
    saveCabinetLog,
    getCabinetByHID,
    storeFaultItem,
    getCabinets,
    openCabinetGrid,
    getCabinetById
};